/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package com.inspur.edp.lcm.metadata.core;

import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.entity.MetadataDto;
import com.inspur.edp.lcm.metadata.api.entity.MetadataHeader;
import com.inspur.edp.lcm.metadata.api.exception.ErrorCodes;
import com.inspur.edp.lcm.metadata.api.exception.LcmMetadataDevException;
import com.inspur.edp.lcm.metadata.cache.MetadataDistCacheManager;
import com.inspur.edp.lcm.metadata.cache.RtCacheHandler;
import com.inspur.edp.lcm.metadata.common.MetadataDtoConverter;
import com.inspur.edp.lcm.metadata.common.configuration.ContentManagerHelper;
import com.inspur.edp.lcm.metadata.common.context.RuntimeContext;
import com.inspur.edp.lcm.metadata.spi.MetadataContentManager;
import com.inspur.edp.metadata.rtcustomization.api.entity.DtSourceTypeEnum;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import io.iec.edp.caf.rpc.api.service.RpcClient;
import io.iec.edp.caf.rpc.api.support.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.UUID;

/**
 * 功能描述:
 *
 * @ClassName: NoCodeCoreService
 * @Author: Fynn Qi
 * @Date: 2021/5/25 15:27
 * @Version: V1.0
 */
public class NoCodeCoreService {

    private final Logger logger= LoggerFactory.getLogger(NoCodeCoreService.class);

    public static NoCodeCoreService getInstance(){
        return Singleton.INSTANCE;
    }

    private static class Singleton{
        static NoCodeCoreService INSTANCE=new NoCodeCoreService();
    }

    public GspMetadata initMetadata(GspMetadata metadata) {
        if(metadata==null){
            throw new LcmMetadataDevException(ErrorCodes.ECP_METADATA_DEV_0005, "metadata");
        }
        if(metadata.getHeader()==null){
            metadata.setHeader(new MetadataHeader());
        }
        if(StringUtils.isEmpty(metadata.getHeader().getId())){
            metadata.getHeader().setId(UUID.randomUUID().toString());
        }
        MetadataContentManager manager = ContentManagerHelper.getInstance().getManager(metadata.getHeader().getType());
        if (manager != null) {
            manager.build(metadata);
        }
        return metadata;
    }

    public GspMetadata saveMetadata(GspMetadata metadata) {
        MetadataDto metadataDto= MetadataDtoConverter.asDto(metadata);
        RpcClient client = SpringBeanUtils.getBean(RpcClient.class);
        LinkedHashMap<String, Object> params = new LinkedHashMap<>();
        params.put("metadataDto", metadataDto);
        MetadataDto response;
        try {
            response = client.invoke(MetadataDto.class, "com.inspur.edp.lcm.metadata.serverapi.NoCodeServerService.saveMetadata", "Lcm", params, null);
        } catch (Exception e) {
            throw new LcmMetadataDevException(e, ErrorCodes.ECP_METADATA_DEV_0008, "com.inspur.edp.lcm.metadata.serverapi.NoCodeServerService.saveMetadata", metadata.getHeader().getId());
        }
        GspMetadata savedMetadata=MetadataDtoConverter.asMetadata(response);
        String language = RuntimeContext.getLanguage();
        String metadataKey = RtCacheHandler.getMetadataCacheKey(savedMetadata.getHeader().getId(), language);
        MetadataDistCacheManager.put(metadataKey, savedMetadata, null);
        return metadata;
    }

    public GspMetadata getMetadata(String metadataId) {
        if (StringUtils.isEmpty(metadataId)) {
            throw new LcmMetadataDevException(ErrorCodes.ECP_METADATA_DEV_0005, "metadataId");
        }
        String language = RuntimeContext.getLanguage();
        String metadataKey = RtCacheHandler.getMetadataCacheKey(metadataId, language);
        GspMetadata metadata = MetadataDistCacheManager.get(metadataKey);
        if (metadata != null) {
            return metadata;
        }
        RpcClient client = SpringBeanUtils.getBean(RpcClient.class);
        LinkedHashMap<String, Object> params = new LinkedHashMap<>();
        params.put("metadataId", metadataId);
        MetadataDto response = null;
        try {
            response = client.invoke(MetadataDto.class, "com.inspur.edp.lcm.metadata.serverapi.NoCodeServerService.getMetadata", "Lcm", params, null);
        } catch (Exception e) {
            throw new LcmMetadataDevException(e, ErrorCodes.ECP_METADATA_DEV_0008, "com.inspur.edp.lcm.metadata.serverapi.NoCodeServerService.getMetadata", metadata.getHeader().getId());
        }
        metadata = MetadataDtoConverter.asMetadata(response);
        if (metadata == null) {
            logger.info("无法找到元数据：" + metadataId);
            return null;
        }
        MetadataDistCacheManager.put(metadataKey, metadata, null);
        return metadata;
    }

    public boolean publishMetadata(String metadataId) {
        if (StringUtils.isEmpty(metadataId)) {
            throw new LcmMetadataDevException(ErrorCodes.ECP_METADATA_DEV_0005, "metadataId");
        }
        RpcClient client = SpringBeanUtils.getBean(RpcClient.class);
        LinkedHashMap<String, Object> params = new LinkedHashMap<>();
        params.put("metadataId", metadataId);
        try {
            return client.invoke(boolean.class, "com.inspur.edp.lcm.metadata.serverapi.NoCodeServerService.publishMetadata", "Lcm", params, null);
        } catch (Exception e) {
            throw new LcmMetadataDevException(e, ErrorCodes.ECP_METADATA_DEV_0008, "com.inspur.edp.lcm.metadata.serverapi.NoCodeServerService.publishMetadata", metadataId);
        }
    }

    public void deleteMetadata(String metadataId) {
        if (StringUtils.isEmpty(metadataId)) {
            throw new LcmMetadataDevException(ErrorCodes.ECP_METADATA_DEV_0005, "metadataId");
        }
        RpcClient client = SpringBeanUtils.getBean(RpcClient.class);
        LinkedHashMap<String, Object> params = new LinkedHashMap<>();
        params.put("metadataId", metadataId);
        try {
            client.invoke(void.class, "com.inspur.edp.lcm.metadata.serverapi.NoCodeServerService.deleteMetadata", "Lcm", params, null);
        } catch (Exception e) {
            throw new LcmMetadataDevException(e, ErrorCodes.ECP_METADATA_DEV_0008, "com.inspur.edp.lcm.metadata.serverapi.NoCodeServerService.deleteMetadata", metadataId);
        }
    }

    public List<MetadataDto> getMetadataListInBO(String bizObjectID) {
        RpcClient client = SpringBeanUtils.getBean(RpcClient.class);
        LinkedHashMap<String, Object> params = new LinkedHashMap<>();
        params.put("sourceType", DtSourceTypeEnum.NOCODE.getCode());
        params.put("bizObjectID", bizObjectID);
        Type<List> type = new Type<>(List.class, MetadataDto.class);
        try {
            return client.invoke(type, "com.inspur.edp.metadata.rtcustomization.serverapi.CustomizationServerService.getAllBySourceTypeAndBizObjectID", "Lcm", params, null);
        } catch (Exception e) {
            throw new LcmMetadataDevException(e, ErrorCodes.ECP_METADATA_DEV_0008, "com.inspur.edp.metadata.rtcustomization.serverapi.CustomizationServerService.getAllBySourceTypeAndBizObjectID", bizObjectID);
        }
    }
}
